package git.soulbgm.common.okhttp;

import git.soulbgm.utils.LogHelper;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 重试拦截器
 *
 * @author SoulBGM
 * @date 2022/03/07 17:03
 */
public class RetryInterceptor implements Interceptor {

    private final LogHelper log = new LogHelper(getClass());

    /**
     * 最大重试次数
     */
    private int maxRetry = 3;
    /**
     * 延迟
     */
    private long delay = 3000;

    public RetryInterceptor() {
    }

    public RetryInterceptor(int maxRetry) {
        this.maxRetry = maxRetry;
    }

    public RetryInterceptor(int maxRetry, long delay) {
        this.maxRetry = maxRetry;
        this.delay = delay;
    }

    /**
     * 拦截
     *
     * @param chain 链
     * @return {@link Response}
     * @throws IOException ioexception
     */
    @Override
    public Response intercept(Chain chain) throws IOException {
        RetryWrapper retryWrapper = proceed(chain);

        while (retryWrapper.isNeedReTry()) {
            retryWrapper.retryNum.getAndIncrement();
            int retryNum = retryWrapper.retryNum.get();
            log.error("访问:{}, 第{}次重试", retryWrapper.request.url().toString(), retryNum);
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
                log.error("执行sleep发生中断异常");
            }
            proceed(chain, retryWrapper.request, retryWrapper);
        }
        return retryWrapper.response == null ? chain.proceed(chain.request()) : retryWrapper.response;
    }

    private RetryWrapper proceed(Chain chain) throws IOException {
        Request request = chain.request();
        RetryWrapper retryWrapper = new RetryWrapper(request, maxRetry);

        proceed(chain, request, retryWrapper);

        return retryWrapper;
    }

    private void proceed(Chain chain, Request request, RetryWrapper retryWrapper) throws IOException {
        try {
            Response response = chain.proceed(request);
            retryWrapper.setResponse(response);
        } catch (SocketException | SocketTimeoutException e) {
            //e.printStackTrace();
        }
    }

    static class RetryWrapper {
        //假如设置为3次重试的话，则最大可能请求5次（默认1次+3次重试 + 最后一次默认）
        AtomicInteger retryNum = new AtomicInteger(0);
        Request request;
        Response response;
        private int maxRetry;

        public RetryWrapper(Request request, int maxRetry) {
            this.request = request;
            this.maxRetry = maxRetry;
        }

        public void setResponse(Response response) {
            this.response = response;
        }

        Response response() {
            return this.response;
        }

        Request request() {
            return this.request;
        }

        public boolean isSuccessful() {
            return response != null && response.isSuccessful();
        }

        public boolean isNeedReTry() {
            return !isSuccessful() && retryNum.get() < maxRetry;
        }

        public void setRetryNum(int retryNum) {
            this.retryNum.set(retryNum);
        }

        public void setMaxRetry(int maxRetry) {
            this.maxRetry = maxRetry;
        }
    }

}
